import { getRSAKey } from '@/api/auth'
// #ifndef H5
import CryptoJS from 'crypto-js'
import JSEncrypt from './jsencrypt'
// #endif

// #ifdef H5
import CryptoJS from 'crypto-es'
import JSEncrypt from 'jsencrypt'
// #endif

class CryptoUtil {
  // 生成信封加密的请求体
  async genEnvelopeInfo(dataStr: string, aesKey: string) {
    // 2. 获取RSA公钥信息
    // 先获取本地RSA公钥信息
    let RSAInfo = JSON.parse(uni.getStorageSync('RSAInfo') || '{}')
    // 判断本地公钥是否过期
    const isValid = this.isRSAInfoValid(RSAInfo)
    if (!RSAInfo || !isValid) {
      // 本地没有或者过期了重新获取
      const result = await getRSAKey()
      RSAInfo = result.data
      uni.setStorageSync('RSAInfo', JSON.stringify(RSAInfo))
    }
    const publicKey = RSAInfo.publicKey
    const expireTime = RSAInfo.expireTime
    // 3. AES秘钥加密消息体
    const data = this.AESEncrypt(dataStr, aesKey)
    // 4. RSA公钥加密AES秘钥
    const aesKeyObj = {
      key: aesKey,
    }
    const key = this.RSAEncrypt(JSON.stringify(aesKeyObj), publicKey)
    const retObj = {
      key: key,
      data: data,
      expireTime: expireTime,
    }
    return retObj
  }

  /* 判断RSAInfo是否过期 */
  isRSAInfoValid(RSAInfoRes: any) {
    if (!RSAInfoRes) return false
    if (!RSAInfoRes.expireTime) return false
    // IOS中不支持yyyy-MM-dd hh:mm:ss形式的时间解析
    const now = Date.now()
    const expireTime = Number(RSAInfoRes.expireTime)
    return expireTime > now
  }

  // AES加密
  AESEncrypt(plainText: string, random: string, iv = 'E08ADE2699714B87') {
    const encrypted = CryptoJS.AES.encrypt(
      CryptoJS.enc.Utf8.parse(plainText),
      CryptoJS.enc.Utf8.parse(random),
      {
        iv: CryptoJS.enc.Utf8.parse(iv),
        mode: CryptoJS.mode.CBC,
        padding: CryptoJS.pad.Pkcs7,
      }
    )
    return encrypted.ciphertext.toString()
  }

  //AES解密
  AESDecrypt(cipherText: string, random: string, iv = 'E08ADE2699714B87') {
    const decrypt = CryptoJS.AES.decrypt(
      CryptoJS.enc.Base64.stringify(CryptoJS.enc.Hex.parse(cipherText)),
      CryptoJS.enc.Utf8.parse(random),
      {
        iv: CryptoJS.enc.Utf8.parse(iv),
        mode: CryptoJS.mode.CBC,
        padding: CryptoJS.pad.Pkcs7,
      }
    )
    return CryptoJS.enc.Utf8.stringify(decrypt).toString()
  }

  //RSA公钥加密
  RSAEncrypt(data: any, publicKey: string) {
    const encryptor = new JSEncrypt()
    encryptor.setPublicKey(publicKey) // 设置公钥
    return encryptor.encrypt(data) // 对数据进行加密
  }

  //RSA私钥解密
  RSADecrypt(data: any, privateKey: string) {
    const encryptor = new JSEncrypt()
    encryptor.setPrivateKey(privateKey) // 设置私钥
    return encryptor.decrypt(data) // 对数据进行解密
  }

  // 生成随机字符串
  randomString(length = 32) {
    const str = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ'
    let result = ''
    for (let i = length; i > 0; --i) {
      result += str[Math.floor(Math.random() * str.length)]
    }
    return result
  }
}

export default new CryptoUtil()
